// 数据导出，目前支持数据的类型：json
package parser

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/360EntSecGroup-Skylar/excelize"
)

type DataMeta struct {
	NameType string // required optional repeated optional_struct 暂时没用
	Name     string // 属性名称
	DataType string // string, int32, float32
	Comment  string
}

var serverFiles []string // A3 逗号分隔的文件名称

// 数据解析单表
func DataSheetParse(rows [][]string, sheet string) (data []interface{}, err string) {
	// 提前创建好底层数组，避免复制
	data = make([]interface{}, 0, len(rows))
	if len(rows) == 0 {
		return
	}

	columnNum := len(rows[0])
	rowNum := len(rows)

	// 元数据列表
	metaList := make([]*DataMeta, columnNum)

	// 包名 A1
	if columnNum > 0 && rowNum > 0 {
		pkg = rows[0][0] //strings.ToLower(rows[0][0]) // 生成的结构体名称
	}
	// 导出文件夹 Scene,Map,Battle  A3
	if columnNum > 0 && rowNum > 2 {
		// dataOutputPath += strings.ToLower(rows[2][0])
		// codeOutputPath += strings.ToLower(rows[2][0])

		spwanFile := strings.Split(strings.ToLower(rows[2][0]), ",")
		for _, name := range spwanFile {
			if strings.Contains(name, "scene") {
				serverFiles = append(serverFiles, "scene")
			} else if strings.Contains(name, "map") {
				serverFiles = append(serverFiles, "map")
			} else if strings.Contains(name, "battle") {
				serverFiles = append(serverFiles, "battle")
			} else if strings.Contains(name, "common") {
				serverFiles = append(serverFiles, "common")
			} else if strings.Contains(name, "clienth") {
				clientNick += "clientH"
			} else if strings.Contains(name, "clientm") {
				clientNick += "clientM"
			}
		}

	}

	// 前4行结构定义
	for j := 1; j < columnNum; j++ {
		// 发现有 "END" 标识 直接返回
		if rows[3][j] == "END" {
			columnNum = j + 1
			break
		}

		meta := &DataMeta{
			// NameType: rows[0][j],
			DataType: rows[2][j],
			Name:     Ucfirst(strings.TrimPrefix(rows[3][j], "_")),
			Comment:  rows[0][j],
		}
		metaList[j] = meta
	}

	// 5行及以后数据
	for i := 4; i < rowNum; i++ {

		// 一行数据
		var item map[string]interface{}
		item, err = DataRowParse(rows[i], metaList, columnNum)
		if err != "" {
			err = fmt.Sprintf("第%d行,%v", i, err)
			return
		}

		data = append(data, item)

		// 最后一行数据用"END"标识
		if rows[i][0] == "END" {
			break
		}

	}

	return
}

// 一行数据解析
func DataRowParse(row []string, metaList []*DataMeta, columnNum int) (item map[string]interface{}, err string) {
	item = make(map[string]interface{})
	for c := 1; c < columnNum; c++ {

		meta := metaList[c]
		// 过滤没有字段名字的行
		if meta == nil || meta.Name == "" {
			continue
		}

		var scalar interface{}
		scalar, err = DataCellParse(meta, row[c])
		if err != "" {
			err = fmt.Sprintf("列名:%v] 错误:%v", meta.Name, err)
			return
		}
		item[meta.Name] = scalar
	}
	return
}

// 单个cell解析
func DataCellParse(meta *DataMeta, value string) (cell interface{}, ret string) {
	var err error
	switch meta.DataType { // 标量逗号分隔
	case "int", "int32", "uint32", "uint64", "int64":
		if value == "" {
			cell = 0
			ret = "空值"
			return
		}
		cell, err = strconv.ParseInt(value, 10, 64)
		if err != nil {
			ret = fmt.Sprintf("类型转换错误::strconv.ParseInt:value %s", value)
		}
	case "string", "String":
		cell = value
	case "float32", "float64", "float":
		if value == "" {
			cell = 0.0
			ret = "空值"
			return
		}
		cell, err = strconv.ParseFloat(value, 64)
		if err != nil {
			ret = fmt.Sprintf("类型转换错误::strconv.ParseFloat:value %s", value)
		}
	case "bool":
		if value == "" {
			cell = false
			ret = "空值"
			return
		}
		cell, err = strconv.ParseBool(value)
		if err != nil {
			ret = fmt.Sprintf("类型转换错误::strconv.ParseBool:value %s", value)
		}
	case "bytes":
		cell = []byte(value)
	default:
		ret = fmt.Sprintf("未识别的cell类型 %s", meta.DataType)
	}

	return
}

// 导出
func DataParse(sheetSlice []string, xlsx *excelize.File) (ret string) {
	mapData := make(map[string]interface{})
	var dataList []interface{}
	Reset()
	for _, sheet := range sheetSlice {
		rows := xlsx.GetRows(sheet)
		if len(rows) <= 0 {
			ret = fmt.Sprintf("[DataParse:sheet:%v] 表不存在或者为空 len(rows):%v", sheet, len(rows))
			return
		}

		sheetData, err := DataSheetParse(rows, sheet)
		if err != "" {
			err = fmt.Sprintf("[sheet:%v,%v", sheet, err)
			return err
		}
		// mapData[sheet] = sheetData
		dataList = append(dataList, sheetData...)

		// 客户端
		_, err = DataSheetParseClient(rows, sheet)
		if err != "" {
			err = fmt.Sprintf("[客户端sheet:%v,%v", sheet, err)
			return err
		}
	}

	mapData[pkg] = dataList

	jsonBytes, err := json.Marshal(mapData)
	if err != nil {
		return err.Error()
	}

	var out bytes.Buffer
	err = json.Indent(&out, jsonBytes, "", "\t")

	if err != nil {
		return err.Error()
	}

	for _, name := range serverFiles {
		outFilename := fmt.Sprintf("%s\\%s.json", dataOutputPath+name, strings.ToLower(pkg))

		outFile, err := os.Create(outFilename)
		defer outFile.Close()
		if err != nil {
			return err.Error()
		}

		_, err = outFile.Write(out.Bytes())
		if err != nil {
			return err.Error()
		}
	}
	if clientNick != "" {
		clientFiles = append(clientFiles, "Hotfix")
		clientFiles = append(clientFiles, "Main")
	}
	fmt.Println("clientFiles", clientFiles)
	for _, name := range clientFiles {
		_ = name // 客户端没有文件夹
		// 客户端json
		outFilename := fmt.Sprintf("%s\\%s.txt", clientDataOutputPath, clientPkg)
		fmt.Println("clientDataOutputPath", clientDataOutputPath)
		outFile, err := os.Create(outFilename)
		defer outFile.Close()
		if err != nil {
			return err.Error()
		}

		_, err = outFile.Write([]byte(clientJson))
		if err != nil {
			return err.Error()
		}
	}

	return

}
